# -*- coding: utf-8 -*-
# 指令发送、打包、解包
import time
import json
from gevent import socket
from agent.client import Demand

try:
    import setting
except ImportError:
    import sys

    sys.path.append('..')
    import setting

from agent.alphabet import OK, NO, TIMEOUT
import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger('interact')
logfile = './interact.log'
File_logging = RotatingFileHandler(logfile, maxBytes=5 * 1024 * 1024, backupCount=50)
File_logging.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
File_logging.setLevel(setting.app['loglevel'])
logger.addHandler(File_logging)
logger.setLevel(setting.app['loglevel'])

request = Demand(log=logger)


def Read(sock):
    while 1:
        d = sock.recv(1)
        if d:
            if d == '[':
                # 解包开始
                k = 0
                version = ''
                identify = ''
                imei = ''
                timezone = ''
                instruct = ''
                raw_params = ''
                params = []
                while 1:
                    d2 = sock.recv(1)
                    if not d2:
                        raise socket.error
                    if d2 == ',':
                        k += 1
                    else:
                        if d2 == ']':
                            break
                        if k == 0:
                            version += d2
                        if k == 1:
                            identify += d2
                        if k == 6:
                            imei += d2
                        if k == 7:
                            timezone += d2
                        if k == 8:
                            instruct += d2.replace('T', 'S')
                        if k == 9:
                            break
                if d2 == ']':
                    break
                else:
                    # 开始解析参数
                    k = 0
                    raw_params += d2
                    while 1:
                        d2 = sock.recv(1)
                        if not d2:
                            raise socket.error
                        if d2 == ',':
                            k += 1
                            params.append(raw_params)
                            raw_params = ''
                            continue
                        if d2 != ']':
                            if k == 2 and (instruct == 'S52' or instruct == 'S53'):
                                # 解析'S52'上传语音文件数据
                                sock.recv(2)
                                # 前三个'\xab',前面读了一个,这里两个
                                while 1:
                                    d2 = sock.recv(1)
                                    if not d2:
                                        raise socket.error
                                    if d2 == '\xab':
                                        d3 = sock.recv(1)
                                        if not d3:
                                            raise socket.error
                                        if d3 == '\xab':
                                            d4 = sock.recv(1)
                                            if not d4:
                                                raise socket.error
                                            if d4 == '\xab':
                                                break
                                            else:
                                                raw_params += d2 + d3 + d4
                                        else:
                                            raw_params += d2 + d3
                                    else:
                                        raw_params += d2
                            else:
                                raw_params += d2
                        else:
                            # ']'指令结束
                            params.append(raw_params)
                            break
                    break
        else:
            raise socket.error
    return version, identify, timezone, imei, instruct, params


def now(timezone=8):
    # return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    if not timezone:
        timezone = 8
    return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.mktime(time.gmtime()) + 3600 * int(timezone)))


def makepack(version, identify, imei, instruct, params=None, timezone=8):
    """
    打包数据为指令格式
    param: version  <str>
    param: identify <str>
    param: imei     <str>
    param: instruct <str>
    param: params   <list>
    """
    if not params:
        params = ''
    else:
        if isinstance(params, list):
            params = ',' + ','.join(params)
    timezone = int(timezone) if timezone else 8
    return '[%s,%s,1,abcd,%s,%s,%s%s]' % (version, identify, now(timezone), imei, instruct, params)


def interact(imei, instruct, params=None):
    """
    对终端发送指令
    param: imei     <str>
    param: instruct <str>
    param: params   <list>
    """
    data = request.send(str(imei), instruct, params)[0]
    return data


def sendtodev(imei, instruct, params):
    """
    向终端发送数据
    param: imei     <str>
    param: instruct <str>
    param: params   <list>
    """
    if not params:
        params = ''
    data = request.send_nowait(str(imei), instruct, params)[0]
    return data


def findimei(imei):
    """
    查找腕表
    """
    data = request.find(str(imei))[0]
    return data


def getlist(page=0, num=20):
    """
    admin获取查看在线终端
    param: page <int>
    param: num  <int>
    """
    length = request.gettotal()[0]
    data = request.getlist(page, num)
    return json.dumps({'len': length, 'list': data})


Fragment = setting.server['audioFragment']


def reduceAudio(imei, f):
    '''
    解析语音数据并发送给终端
    param: imei <str>
    param: f    <StringIO.StringIO>
    '''
    i = 0
    l = str(f.len)
    r = sendtodev(imei, 'S53', ['START', l])
    while r == OK:
        data = f.read(Fragment)
        if data:
            r = interact(imei, 'S53', ['DOWN', str(i), '\xab\xab\xab' + data + '\xab\xab\xab'])
            # S53 需要腕表确认
            i += 1
        else:
            break
    r = sendtodev(imei, 'S53', ['END', l]) if r == OK else NO
    return r
